package cn.well.cloud.quartz.core.task.api.impl;

import cn.stylefeng.roses.kernel.model.response.ResponseData;
import cn.well.cloud.quartz.core.model.ScheduleJob;
import cn.well.cloud.quartz.core.task.ResultHandler;
import cn.well.cloud.quartz.core.task.TaskUtils;
import cn.well.cloud.quartz.core.task.api.JobOperationAPI;
import cn.well.cloud.quartz.core.task.api.OperationAPI;
import cn.well.cloud.quartz.core.task.exception.TaskApiException;
import cn.well.cloud.quartz.modular.model.Timetask;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
public class JobOperation implements JobOperationAPI{

    @Autowired
    private ResultHandler resultHandler;

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Autowired
    private TaskUtils taskUtils;

    @Override
    public Object getAllJob() {
        return resultHandler.handle(new OperationAPI() {
            @Override
            public Object invokeOperationAPI() throws TaskApiException, SchedulerException {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
                Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
                List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
                for (JobKey jobKey : jobKeys) {
                    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                    for (Trigger trigger : triggers) {
                        ScheduleJob job = new ScheduleJob();
                        job.setJobId(trigger.getDescription());// description 放的是job的id
                        job.setJobName(jobKey.getName());
                        job.setJobGroup(jobKey.getGroup());
                        job.setDescription("触发器:" + trigger.getKey());
                        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                        job.setJobStatus(triggerState.name());
                        if (trigger instanceof CronTrigger) {
                            CronTrigger cronTrigger = (CronTrigger) trigger;
                            String cronExpression = cronTrigger.getCronExpression();
                            job.setCronExpression(cronExpression);
                        }
                        jobList.add(job);
                    }
                }
                return ResponseData.success(jobList);
            }
        });
    }

    @Override
    public Object getRunningJob() {
        return resultHandler.handle(new OperationAPI() {
            @Override
            public Object invokeOperationAPI() throws TaskApiException, SchedulerException {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
                List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());
                for (JobExecutionContext executingJob : executingJobs) {
                    ScheduleJob job = new ScheduleJob();
                    JobDetail jobDetail = executingJob.getJobDetail();
                    JobKey jobKey = jobDetail.getKey();
                    Trigger trigger = executingJob.getTrigger();
                    job.setJobId(trigger.getDescription());// description 放的是job的id
                    job.setJobName(jobKey.getName());
                    job.setJobGroup(jobKey.getGroup());
                    job.setDescription("触发器:" + trigger.getKey());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    job.setJobStatus(triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        job.setCronExpression(cronExpression);
                    }
                    jobList.add(job);
                }
                return ResponseData.success(jobList);
            }
        });
    }

    @Override
    public Object addJob(Timetask timetask) {
        return resultHandler.handle(new OperationAPI() {
            @Override
            public Object invokeOperationAPI() throws TaskApiException, SchedulerException {
                ScheduleJob job = new ScheduleJob();
                if (timetask != null) {
                    job.setJobId(timetask.getTaskId().toString());
                    job.setJobGroup(timetask.getGroupName()); // 任务组
                    job.setJobName(timetask.getName());// 任务名称
                    job.setJobStatus(timetask.getJobStatus()); // 任务发布状态
                    job.setIsConcurrent(timetask.getConcurrent().toString()); // 运行状态
                    job.setCronExpression(timetask.getCron());
                    job.setBeanClass(timetask.getBeanName());// 一个以所给名字注册的bean的实例
                    job.setMethodName(timetask.getMethodName());
                    job.setJobData(timetask.getJobData()); // 参数
                }
                taskUtils.addJob(job);
                return ResponseData.success();
            }
        });
    }

    @Override
    public Object pauseJob(String name, String groupName) {
        return resultHandler.handle(new OperationAPI() {
            @Override
            public Object invokeOperationAPI() throws TaskApiException, SchedulerException {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(name, groupName);
                scheduler.pauseJob(jobKey);
                return ResponseData.success();
            }
        });
    }

    @Override
    public Object resumeJob(String name, String groupName) {
        return resultHandler.handle(new OperationAPI() {
            @Override
            public Object invokeOperationAPI() throws TaskApiException, SchedulerException {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(name, groupName);
                scheduler.resumeJob(jobKey);
                return ResponseData.success();
            }
        });
    }

    @Override
    public Object deleteJob(String name, String groupName) {
        return resultHandler.handle(new OperationAPI() {
            @Override
            public Object invokeOperationAPI() throws TaskApiException, SchedulerException {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(name, groupName);
                scheduler.deleteJob(jobKey);
                return ResponseData.success();
            }
        });
    }

    @Override
    public Object runAJobNow(String name, String groupName) {
        return resultHandler.handle(new OperationAPI() {
            @Override
            public Object invokeOperationAPI() throws TaskApiException, SchedulerException {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                JobKey jobKey = JobKey.jobKey(name, groupName);
                scheduler.triggerJob(jobKey);
                return ResponseData.success();
            }
        });
    }

    @Override
    public Object updateJobCron(String name, String groupName, String cron) {
        return resultHandler.handle(new OperationAPI() {
            @Override
            public Object invokeOperationAPI() throws TaskApiException, SchedulerException {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                TriggerKey triggerKey = TriggerKey.triggerKey(name, groupName);
                CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
                scheduler.rescheduleJob(triggerKey, trigger);
                return ResponseData.success();
            }
        });
    }
}
